#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>
#include <math.h>

int fds[4][2] = {0}; // fds[i][0] - key, fds[i][1] - led
int ino[4][2] = {{6,5},{13,22},{19,27},{26,17}};
char sta[4], last[4] = {0};
long long  base;
float delay_calibration = 0;

#define TIME_UNIT 1000

float pi(){
    float s = 1, pi = 0, i = 1.0, n = 1.0;
    while (fabs(i) >= 1e-7){
        pi += i;
        n = n + 2;
        s = -s; 
        i = s/n;
    }
    pi =4* pi;
    //printf("pi: %.6f\n",pi);
    return pi;
}

char rev_led(char k){
    return k==48?49:48;
}

void get_base(){
    struct timeval tv;
    gettimeofday(&tv,NULL);
    base = tv.tv_sec * 1000 + tv.tv_usec / 1000;
}

time_t get_clock(){
    struct timeval tv;
    gettimeofday(&tv,NULL);
    return (tv.tv_sec * 1000 + tv.tv_usec / 1000) - base;
}

void plog(char *s){
    struct timeval tv;
    gettimeofday(&tv,NULL);
    printf("%ld: %s\n", (tv.tv_sec * 1000 + tv.tv_usec / 1000) - base, s);
    //printf("%ld: %s\n", get_clock());
}

void delay(time_t us){
    int count = us/TIME_UNIT*delay_calibration;
    for (int i=0; i<1; i++){
        pi();
    }
}

void calibration(time_t us){
    struct timeval tv;
    time_t start = get_clock();
    for (int i=0; get_clock() < start + us; i++){
        gettimeofday(&tv,NULL);
        delay_calibration = (float)i/(us/TIME_UNIT);
        pi();
    }
    printf("delay_calibration: %f\n", delay_calibration);
}

void change_led(char status, int fd) {
    lseek(fd, 0, SEEK_SET);
    write(fd, &status, 1);
    return;
}

void blink_led(char status, int fd){
    for (int i=0; i<5000000; i++){
        //plog("blink");
        change_led(status, fd);
        status = rev_led(status);
        delay(200*TIME_UNIT);
    }
}

int open_dev(){
    char t[64];
    for (int i=0; i<4; i++){
        sprintf(t, "/sys/class/gpio/gpio%d/value", ino[i][0]);
        fds[i][0] = open(t, O_RDONLY, 0777);
        sprintf(t, "/sys/class/gpio/gpio%d/value", ino[i][1]);
        fds[i][1] = open(t, O_RDWR, 0777);
    }
}

int close_dev(){
    for (int i=0; i<4; i++){
        close(fds[i][0]);
        close(fds[i][1]);
    }
}

int main(){   
    get_base();
    open_dev();

    plog("start pi");
    pi();
    plog("stop pi");

    //calibration(1000*TIME_UNIT);

    for (int i=0;i<4;i=++i%4){
        //lseek(fds[i][0], 0, SEEK_SET);
        //read(fds[i][0], &sta[i], 1);
        //if (sta[i] != last[i])
        {
            //printf("%d %d\n", i, sta[i]);
            last[i] = sta[i] == 48 ? 49 : 48;
            blink_led(rev_led(sta[i]), fds[1][1]);
        }
    }

    return 0;
}








